home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland Pascal with Objects 7.0 / TVDEMO.ZIP / TVDEMO.PAS < prev    next >
Pascal/Delphi Source File  |  1992-10-27  |  19KB  |  692 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. program TVDemo;
  9.  
  10. {$X+,S-}
  11. {$M 16384,8192,655360}
  12.  
  13. { Turbo Vision demo program. This program uses many of the Turbo
  14.   Vision standard and demo units, including:
  15.  
  16.     StdDlg    - Open file browser, change directory tree.
  17.     MsgBox    - Simple dialog to display messages.
  18.     ColorSel  - Color customization.
  19.     Gadgets   - Shows system time and available heap space.
  20.     AsciiTab  - ASCII table.
  21.     Calendar  - View a month at a time
  22.     Calc      - Desktop calculator.
  23.     HelpFile  - Context sensitive help.
  24.     MouseDlg  - Mouse options dialog.
  25.     Puzzle    - Simple brain puzzle.
  26.     Editors   - Text Editor object.
  27.  
  28.   And of course this program includes many standard Turbo Vision
  29.   objects and behaviors (menubar, desktop, status line, dialog boxes,
  30.   mouse support, window resize/move/tile/cascade).
  31. }
  32.  
  33. uses
  34.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, HistList,
  35.   MsgBox, App, DemoCmds, Gadgets, Puzzle, Calendar, AsciiTab, Calc,
  36.   HelpFile, DemoHelp, ColorSel, MouseDlg, Editors;
  37.  
  38. { If you get a FILE NOT FOUND error when compiling this program
  39.   from a DOS IDE, change to the \BP\EXAMPLES\DOS\TVDEMO directory
  40.   (use File|Change dir).
  41.  
  42.   This will enable the compiler to find all of the units used by
  43.   this program.
  44. }
  45.  
  46. const
  47.   HeapSize = 48 * (1024 div 16);  { Save 48k heap for main program }
  48.  
  49.   { Desktop file signature information }
  50.   SignatureLen = 21;
  51.   DSKSignature : string[SignatureLen] = 'TV Demo Desktop File'#26;
  52.  
  53. var
  54.   ClipWindow: PEditWindow;
  55.  
  56. type
  57.  
  58.   { TTVDemo }
  59.  
  60.   PTVDemo = ^TTVDemo;
  61.   TTVDemo = object(TApplication)
  62.     Clock: PClockView;
  63.     Heap: PHeapView;
  64.     constructor Init;
  65.     procedure FileOpen(WildCard: PathStr);
  66.     function OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  67.     procedure GetEvent(var Event: TEvent); virtual;
  68.     function GetPalette: PPalette; virtual;
  69.     procedure HandleEvent(var Event: TEvent); virtual;
  70.     procedure Idle; virtual;
  71.     procedure InitMenuBar; virtual;
  72.     procedure InitStatusLine; virtual;
  73.     procedure LoadDesktop(var S: TStream);
  74.     procedure OutOfMemory; virtual;
  75.     procedure StoreDesktop(var S: TStream);
  76.   end;
  77.  
  78. { CalcHelpName }
  79.  
  80. function CalcHelpName: PathStr;
  81. var
  82.   EXEName: PathStr;
  83.   Dir: DirStr;
  84.   Name: NameStr;
  85.   Ext: ExtStr;
  86. begin
  87.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  88.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  89.   FSplit(EXEName, Dir, Name, Ext);
  90.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  91.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  92. end;
  93.  
  94. function CreateFindDialog: PDialog;
  95. var
  96.   D: PDialog;
  97.   Control: PView;
  98.   R: TRect;
  99. begin
  100.   R.Assign(0, 0, 38, 12);
  101.   D := New(PDialog, Init(R, 'Find'));
  102.   with D^ do
  103.   begin
  104.     Options := Options or ofCentered;
  105.  
  106.     R.Assign(3, 3, 32, 4);
  107.     Control := New(PInputLine, Init(R, 80));
  108.     Insert(Control);
  109.     R.Assign(2, 2, 15, 3);
  110.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  111.     R.Assign(32, 3, 35, 4);
  112.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  113.  
  114.     R.Assign(3, 5, 35, 7);
  115.     Insert(New(PCheckBoxes, Init(R,
  116.       NewSItem('~C~ase sensitive',
  117.       NewSItem('~W~hole words only', nil)))));
  118.  
  119.     R.Assign(14, 9, 24, 11);
  120.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  121.     Inc(R.A.X, 12); Inc(R.B.X, 12);
  122.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  123.  
  124.     SelectNext(False);
  125.   end;
  126.   CreateFindDialog := D;
  127. end;
  128.  
  129. function CreateReplaceDialog: PDialog;
  130. var
  131.   D: PDialog;
  132.   Control: PView;
  133.   R: TRect;
  134. begin
  135.   R.Assign(0, 0, 40, 16);
  136.   D := New(PDialog, Init(R, 'Replace'));
  137.   with D^ do
  138.   begin
  139.     Options := Options or ofCentered;
  140.  
  141.     R.Assign(3, 3, 34, 4);
  142.     Control := New(PInputLine, Init(R, 80));
  143.     Insert(Control);
  144.     R.Assign(2, 2, 15, 3);
  145.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  146.     R.Assign(34, 3, 37, 4);
  147.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  148.  
  149.     R.Assign(3, 6, 34, 7);
  150.     Control := New(PInputLine, Init(R, 80));
  151.     Insert(Control);
  152.     R.Assign(2, 5, 12, 6);
  153.     Insert(New(PLabel, Init(R, '~N~ew text', Control)));
  154.     R.Assign(34, 6, 37, 7);
  155.     Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
  156.  
  157.     R.Assign(3, 8, 37, 12);
  158.     Insert(New(PCheckBoxes, Init(R,
  159.       NewSItem('~C~ase sensitive',
  160.       NewSItem('~W~hole words only',
  161.       NewSItem('~P~rompt on replace',
  162.       NewSItem('~R~eplace all', nil)))))));
  163.  
  164.     R.Assign(17, 13, 27, 15);
  165.     Insert(New(PButton, Init(R, 'O~K~', cmOk, bfDefault)));
  166.     R.Assign(28, 13, 38, 15);
  167.     Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  168.  
  169.     SelectNext(False);
  170.   end;
  171.   CreateReplaceDialog := D;
  172. end;
  173.  
  174. function DoEditDialog(Dialog: Integer; Info: Pointer): Word; far;
  175. var
  176.   R: TRect;
  177.   T: TPoint;
  178. begin
  179.   case Dialog of
  180.     edOutOfMemory:
  181.       DoEditDialog := MessageBox('Not enough memory for this operation.',
  182.         nil, mfError + mfOkButton);
  183.     edReadError:
  184.       DoEditDialog := MessageBox('Error reading file %s.',
  185.         @Info, mfError + mfOkButton);
  186.     edWriteError:
  187.       DoEditDialog := MessageBox('Error writing file %s.',
  188.         @Info, mfError + mfOkButton);
  189.     edCreateError:
  190.       DoEditDialog := MessageBox('Error creating file %s.',
  191.         @Info, mfError + mfOkButton);
  192.     edSaveModify:
  193.       DoEditDialog := MessageBox('%s has been modified. Save?',
  194.         @Info, mfInformation + mfYesNoCancel);
  195.     edSaveUntitled:
  196.       DoEditDialog := MessageBox('Save untitled file?',
  197.         nil, mfInformation + mfYesNoCancel);
  198.     edSaveAs:
  199.       DoEditDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
  200.         'Save file as', '~N~ame', fdOkButton, 101)), Info);
  201.     edFind:
  202.       DoEditDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
  203.     edSearchFailed:
  204.       DoEditDialog := MessageBox('Search string not found.',
  205.         nil, mfError + mfOkButton);
  206.     edReplace:
  207.       DoEditDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
  208.     edReplacePrompt:
  209.       begin
  210.         { Avoid placing the dialog on the same line as the cursor }
  211.         R.Assign(0, 1, 40, 8);
  212.         R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  213.         Desktop^.MakeGlobal(R.B, T);
  214.         Inc(T.Y);
  215.         if TPoint(Info).Y <= T.Y then
  216.           R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  217.         DoEditDialog := MessageBoxRect(R, 'Replace this occurence?',
  218.           nil, mfYesNoCancel + mfInformation);
  219.       end;
  220.   end;
  221. end;
  222.  
  223. { TTVDemo }
  224. constructor TTVDemo.Init;
  225. var
  226.   R: TRect;
  227.   I: Integer;
  228.   FileName: PathStr;
  229. begin
  230.   MaxHeapSize := HeapSize;
  231.   inherited Init;
  232.   RegisterObjects;
  233.   RegisterViews;
  234.   RegisterMenus;
  235.   RegisterDialogs;
  236.   RegisterApp;
  237.   RegisterHelpFile;
  238.   RegisterPuzzle;
  239.   RegisterCalendar;
  240.   RegisterAsciiTab;
  241.   RegisterCalc;
  242.   RegisterEditors;
  243.  
  244.   { Initialize demo gadgets }
  245.  
  246.   GetExtent(R);
  247.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  248.   Clock := New(PClockView, Init(R));
  249.   Insert(Clock);
  250.  
  251.   GetExtent(R);
  252.   Dec(R.B.X);
  253.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  254.   Heap := New(PHeapView, Init(R));
  255.   Insert(Heap);
  256.  
  257.   DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  258.     cmUndo, cmFind, cmReplace, cmSearchAgain, cmCloseAll]);
  259.   EditorDialog := DoEditDialog;
  260.   ClipWindow := OpenEditor('', False);
  261.   if ClipWindow <> nil then
  262.   begin
  263.     Clipboard := ClipWindow^.Editor;
  264.     Clipboard^.CanUndo := False;
  265.   end;
  266.  
  267.   for I := 1 to ParamCount do
  268.   begin
  269.     FileName := ParamStr(I);
  270.     if FileName[Length(FileName)] = '\' then
  271.       FileName := FileName + '*.*';
  272.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  273.       OpenEditor(FExpand(FileName), True)
  274.     else FileOpen(FileName);
  275.   end;
  276. end;
  277.  
  278. function TTVDemo.OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  279. var
  280.   P: PView;
  281.   R: TRect;
  282. begin
  283.   DeskTop^.GetExtent(R);
  284.   P := Application^.ValidView(New(PEditWindow,
  285.     Init(R, FileName, wnNoNumber)));
  286.   if not Visible then P^.Hide;
  287.   DeskTop^.Insert(P);
  288.   OpenEditor := PEditWindow(P);
  289. end;
  290.  
  291. procedure TTVDemo.FileOpen(WildCard: PathStr);
  292. var
  293.   FileName: FNameStr;
  294. begin
  295.   FileName := '*.*';
  296.   if ExecuteDialog(New(PFileDialog, Init(WildCard, 'Open a file',
  297.     '~N~ame', fdOpenButton + fdHelpButton, 100)), @FileName) <> cmCancel then
  298.     OpenEditor(FileName, True);
  299. end;
  300.  
  301. procedure TTVDemo.GetEvent(var Event: TEvent);
  302. var
  303.   W: PWindow;
  304.   HFile: PHelpFile;
  305.   HelpStrm: PDosStream;
  306. const
  307.   HelpInUse: Boolean = False;
  308. begin
  309.   inherited GetEvent(Event);
  310.   case Event.What of
  311.     evCommand:
  312.       if (Event.Command = cmHelp) and not HelpInUse then
  313.       begin
  314.         HelpInUse := True;
  315.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  316.         HFile := New(PHelpFile, Init(HelpStrm));
  317.         if HelpStrm^.Status <> stOk then
  318.         begin
  319.           MessageBox('Could not open help file.', nil, mfError + mfOkButton);
  320.           Dispose(HFile, Done);
  321.         end
  322.         else
  323.         begin
  324.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  325.           if ValidView(W) <> nil then
  326.           begin
  327.             ExecView(W);
  328.             Dispose(W, Done);
  329.           end;
  330.           ClearEvent(Event);
  331.         end;
  332.         HelpInUse := False;
  333.       end;
  334.     evMouseDown:
  335.       if Event.Buttons <> 1 then Event.What := evNothing;
  336.   end;
  337. end;
  338.  
  339. function TTVDemo.GetPalette: PPalette;
  340. const
  341.   CNewColor = CAppColor + CHelpColor;
  342.   CNewBlackWhite = CAppBlackWhite + CHelpBlackWhite;
  343.   CNewMonochrome = CAppMonochrome + CHelpMonochrome;
  344.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  345.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  346. begin
  347.   GetPalette := @P[AppPalette];
  348. end;
  349.  
  350. procedure TTVDemo.HandleEvent(var Event: TEvent);
  351.  
  352. procedure ChangeDir;
  353. var
  354.   D: PChDirDialog;
  355. begin
  356.   D := New(PChDirDialog, Init(cdNormal + cdHelpButton, 101));
  357.   D^.HelpCtx := hcFCChDirDBox;
  358.   ExecuteDialog(D, nil);
  359. end;
  360.  
  361. procedure Puzzle;
  362. var
  363.   P: PPuzzleWindow;
  364. begin
  365.   P := New(PPuzzleWindow, Init);
  366.   P^.HelpCtx := hcPuzzle;
  367.   InsertWindow(P);
  368. end;
  369.  
  370. procedure Calendar;
  371. var
  372.   P: PCalendarWindow;
  373. begin
  374.   P := New(PCalendarWindow, Init);
  375.   P^.HelpCtx := hcCalendar;
  376.   InsertWindow(P);
  377. end;
  378.  
  379. procedure About;
  380. var
  381.   D: PDialog;
  382.   Control: PView;
  383.   R: TRect;
  384. begin
  385.   R.Assign(0, 0, 40, 11);
  386.   D := New(PDialog, Init(R, 'About'));
  387.   with D^ do
  388.   begin
  389.     Options := Options or ofCentered;
  390.  
  391.     R.Grow(-1, -1);
  392.     Dec(R.B.Y, 3);
  393.     Insert(New(PStaticText, Init(R,
  394.       #13 +
  395.       ^C'Turbo Vision Demo'#13 +
  396.       #13 +
  397.       ^C'Copyright (c) 1992'#13 +
  398.       #13 +
  399.       ^C'Borland International')));
  400.  
  401.     R.Assign(15, 8, 25, 10);
  402.     Insert(New(PButton, Init(R, 'O~K', cmOk, bfDefault)));
  403.   end;
  404.   if ValidView(D) <> nil then
  405.   begin
  406.     Desktop^.ExecView(D);
  407.     Dispose(D, Done);
  408.   end;
  409. end;
  410.  
  411. procedure AsciiTab;
  412. var
  413.   P: PAsciiChart;
  414. begin
  415.   P := New(PAsciiChart, Init);
  416.   P^.HelpCtx := hcAsciiTable;
  417.   InsertWindow(P);
  418. end;
  419.  
  420. procedure Calculator;
  421. var
  422.   P: PCalculator;
  423. begin
  424.   P := New(PCalculator, Init);
  425.   P^.HelpCtx := hcCalculator;
  426.   InsertWindow(P);
  427. end;
  428.  
  429. procedure Colors;
  430. var
  431.   D: PColorDialog;
  432. begin
  433.   D := New(PColorDialog, Init('',
  434.     ColorGroup('Desktop',       DesktopColorItems(nil),
  435.     ColorGroup('Menus',         MenuColorItems(nil),
  436.     ColorGroup('Dialogs/Calc',  DialogColorItems(dpGrayDialog, nil),
  437.     ColorGroup('Editor/Puzzle', WindowColorItems(wpBlueWindow, nil),
  438.     ColorGroup('Ascii table',   WindowColorItems(wpGrayWindow, nil),
  439.     ColorGroup('Calendar',
  440.       WindowColorItems(wpCyanWindow,
  441.       ColorItem('Current day',       22, nil)),
  442.       nil))))))));
  443.  
  444.   D^.HelpCtx := hcOCColorsDBox;
  445.  
  446.   if ExecuteDialog(D, Application^.GetPalette) <> cmCancel then
  447.   begin
  448.     DoneMemory;    { Dispose all group buffers }
  449.     ReDraw;        { Redraw application with new palette }
  450.   end;
  451. end;
  452.  
  453. procedure Mouse;
  454. var
  455.   D: PDialog;
  456. begin
  457.   D := New(PMouseDialog, Init);
  458.   D^.HelpCtx := hcOMMouseDBox;
  459.   ExecuteDialog(D, @MouseReverse);
  460. end;
  461.  
  462. procedure RetrieveDesktop;
  463. var
  464.   S: PStream;
  465.   Signature: string[SignatureLen];
  466. begin
  467.   S := New(PBufStream, Init('TVDEMO.DSK', stOpenRead, 1024));
  468.   if LowMemory then OutOfMemory
  469.   else if S^.Status <> stOk then
  470.     MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
  471.   else
  472.   begin
  473.     Signature[0] := Char(SignatureLen);
  474.     S^.Read(Signature[1], SignatureLen);
  475.     if Signature = DSKSignature then
  476.     begin
  477.       LoadDesktop(S^);
  478.       LoadIndexes(S^);
  479.       LoadHistory(S^);
  480.       if S^.Status <> stOk then
  481.         MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
  482.     end
  483.     else
  484.       MessageBox('Error: Invalid Desktop file.', nil, mfOkButton + mfError);
  485.   end;
  486.   Dispose(S, Done);
  487. end;
  488.  
  489. procedure SaveDesktop;
  490. var
  491.   S: PStream;
  492.   F: File;
  493. begin
  494.   S := New(PBufStream, Init('TVDEMO.DSK', stCreate, 1024));
  495.   if not LowMemory and (S^.Status = stOk) then
  496.   begin
  497.     S^.Write(DSKSignature[1], SignatureLen);
  498.     StoreDesktop(S^);
  499.     StoreIndexes(S^);
  500.     StoreHistory(S^);
  501.     if S^.Status <> stOk then
  502.     begin
  503.       MessageBox('Could not create TVDEMO.DSK.', nil, mfOkButton + mfError);
  504.       {$I-}
  505.       Dispose(S, Done);
  506.       Assign(F, 'TVDEMO.DSK');
  507.       Erase(F);
  508.       Exit;
  509.     end;
  510.   end;
  511.   Dispose(S, Done);
  512. end;
  513.  
  514. procedure FileNew;
  515. begin
  516.   OpenEditor('', True);
  517. end;
  518.  
  519. procedure ShowClip;
  520. begin
  521.   ClipWindow^.Select;
  522.   ClipWindow^.Show;
  523. end;
  524.  
  525. begin
  526.   inherited HandleEvent(Event);
  527.   case Event.What of
  528.     evCommand:
  529.       begin
  530.         case Event.Command of
  531.           cmOpen: FileOpen('*.*');
  532.           cmNew: FileNew;
  533.           cmShowClip: ShowClip;
  534.           cmChangeDir: ChangeDir;
  535.           cmAbout: About;
  536.           cmPuzzle: Puzzle;
  537.           cmCalendar: Calendar;
  538.           cmAsciiTab: AsciiTab;
  539.           cmCalculator: Calculator;
  540.           cmColors: Colors;
  541.           cmMouse: Mouse;
  542.           cmSaveDesktop: SaveDesktop;
  543.           cmRetrieveDesktop: RetrieveDesktop;
  544.         else
  545.           Exit;
  546.         end;
  547.         ClearEvent(Event);
  548.       end;
  549.   end;
  550. end;
  551.  
  552. procedure TTVDemo.Idle;
  553.  
  554. function IsTileable(P: PView): Boolean; far;
  555. begin
  556.   IsTileable := (P^.Options and ofTileable <> 0) and
  557.     (P^.State and sfVisible <> 0);
  558. end;
  559.  
  560. begin
  561.   inherited Idle;
  562.   Clock^.Update;
  563.   Heap^.Update;
  564.   if Desktop^.FirstThat(@IsTileable) <> nil then
  565.     EnableCommands([cmTile, cmCascade])
  566.   else
  567.     DisableCommands([cmTile, cmCascade]);
  568. end;
  569.  
  570. procedure TTVDemo.InitMenuBar;
  571. var
  572.   R: TRect;
  573. begin
  574.   GetExtent(R);
  575.   R.B.Y := R.A.Y+1;
  576.   MenuBar := New(PMenuBar, Init(R, NewMenu(
  577.     NewSubMenu('~'#240'~', hcSystem, NewMenu(
  578.       NewItem('~A~bout', '', kbNoKey, cmAbout, hcSAbout,
  579.       NewLine(
  580.       NewItem('~P~uzzle', '', kbNoKey, cmPuzzle, hcSPuzzle,
  581.       NewItem('Ca~l~endar', '', kbNoKey, cmCalendar, hcSCalendar,
  582.       NewItem('Ascii ~t~able', '', kbNoKey, cmAsciiTab, hcSAsciiTable,
  583.       NewItem('~C~alculator', '', kbNoKey, cmCalculator, hcCalculator, nil))))))),
  584.     NewSubMenu('~F~ile', hcFile, NewMenu(
  585.       StdFileMenuItems(nil)),
  586.     NewSubMenu('~E~dit', hcEdit, NewMenu(
  587.       StdEditMenuItems(
  588.       NewLine(
  589.       NewItem('~S~how clipboard', '', kbNoKey, cmShowClip, hcShowClip,
  590.       nil)))),
  591.     NewSubMenu('~S~earch', hcSearch, NewMenu(
  592.       NewItem('~F~ind...', '', kbNoKey, cmFind, hcFind,
  593.       NewItem('~R~eplace...', '', kbNoKey, cmReplace, hcReplace,
  594.       NewItem('~S~earch again', '', kbNoKey, cmSearchAgain, hcSearchAgain,
  595.       nil)))),
  596.     NewSubMenu('~W~indow', hcWindows, NewMenu(
  597.       StdWindowMenuItems(nil)),
  598.     NewSubMenu('~O~ptions', hcOptions, NewMenu(
  599.       NewItem('~M~ouse...', '', kbNoKey, cmMouse, hcOMouse,
  600.       NewItem('~C~olors...', '', kbNoKey, cmColors, hcOColors,
  601.       NewLine(
  602.       NewItem('~S~ave desktop', '', kbNoKey, cmSaveDesktop, hcOSaveDesktop,
  603.       NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcORestoreDesktop, nil)))))),
  604.       nil)))))))));
  605. end;
  606.  
  607. procedure TTVDemo.InitStatusLine;
  608. var
  609.   R: TRect;
  610. begin
  611.   GetExtent(R);
  612.   R.A.Y := R.B.Y - 1;
  613.   StatusLine := New(PStatusLine, Init(R,
  614.     NewStatusDef(0, $FFFF,
  615.       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  616.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  617.       NewStatusKey('~F3~ Open', kbF3, cmOpen,
  618.       NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  619.       NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
  620.       NewStatusKey('', kbF10, cmMenu,
  621.       NewStatusKey('', kbCtrlF5, cmResize,
  622.       nil))))))),
  623.     nil)));
  624. end;
  625.  
  626. procedure TTVDemo.OutOfMemory;
  627. begin
  628.   MessageBox('Not enough memory available to complete operation.',
  629.     nil, mfError + mfOkButton);
  630. end;
  631.  
  632. { Since the safety pool is only large enough to guarantee that allocating
  633.   a window will not run out of memory, loading the entire desktop without
  634.   checking LowMemory could cause a heap error.  This means that each
  635.   window should be read individually, instead of using Desktop's Load.
  636. }
  637.  
  638. procedure TTVDemo.LoadDesktop(var S: TStream);
  639. var
  640.   P: PView;
  641.   Pal: PString;
  642.  
  643. procedure CloseView(P: PView); far;
  644. begin
  645.   Message(P, evCommand, cmClose, nil);
  646. end;
  647.  
  648. begin
  649.   if Desktop^.Valid(cmClose) then
  650.   begin
  651.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  652.     repeat
  653.       P := PView(S.Get);
  654.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  655.     until P = nil;
  656.     Pal := S.ReadStr;
  657.     if Pal <> nil then
  658.     begin
  659.       Application^.GetPalette^ := Pal^;
  660.       DoneMemory;
  661.       Application^.ReDraw;
  662.       DisposeStr(Pal);
  663.     end;
  664.   end;
  665. end;
  666.  
  667. procedure TTVDemo.StoreDesktop(var S: TStream);
  668. var
  669.   Pal: PString;
  670.  
  671. procedure WriteView(P: PView); far;
  672. begin
  673.   if P <> Desktop^.Last then S.Put(P);
  674. end;
  675.  
  676. begin
  677.   Desktop^.ForEach(@WriteView);
  678.   S.Put(nil);
  679.   Pal := @Application^.GetPalette^;
  680.   S.WriteStr(Pal);
  681. end;
  682.  
  683.  
  684. var
  685.   Demo: TTVDemo;
  686.  
  687. begin
  688.   Demo.Init;
  689.   Demo.Run;
  690.   Demo.Done;
  691. end.
  692.